/*******************************************************************************
 *	                           bsp cpu.c
 *******************************************************************************/
#include "bsp.h"
#include "bsp_adc.h"
#include "framework.h"

/*******************************************************************************
 * @brief   order
 ******************************************************************************/
obj_init_app(adc_task_init);

/*******************************************************************************
 * @brief   fun
 ******************************************************************************/
adc_man_type adc_man;

void adc_for_sys_vol(void);
void adc_inject_handle(void);
void adc_regular_handle(void);
void adc_sampletime_cfg(void);
void adc_trans_channel_cfg(void);
void adc_dma_cfg(void);
void adc_regular_start(void);

/*******************************************************************************
 * @brief   init
 ******************************************************************************/
void adc_task_init(void)
{
	// app_timer_task_add(adc_inject_handle);
	app_timer_task_add(adc_regular_handle);
}

/*******************************************************************************
 * @brief   Adc task.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 ******************************************************************************/
void adc_inject_handle(void)
{
	if (adc_man.tune_st == 1)
	{
		/* 校准 */
		// adc_calibration_start(ADC1);
		adc_man.tune_st = 2;
	}
	else if (adc_man.tune_st == 2)
	{
		adc_man.tune_st = 0;

		/* 开启注入转换 */
		ADC1->CTRL1_B.SCANEN = BIT_SET;
		ADC1->CTRL2_B.INJSWSC = BIT_SET;
	}
	else if (ADC1->STS_B.INJEOCFLG)
	{
		adc_man.time_out = 0;
		adc_man.cnt++;
		ADC1->STS = 0;

		/* 取值 累计 */
		loop(4)
		{
			adc_man.real[index] = (&(ADC1->INJDATA1))[index] & 0x0FFF;
			adc_man.sum[index] += adc_man.real[index];
		}

		/* 电压判断 */
		adc_for_sys_vol();

		/* 过采样，工频倍数，取100ms */
		if (adc_man.cnt >= 100)
		{
			adc_man.cnt = 0;
			adc_man.st_hal_end = 1;

			adc_man.list_index++;
			adc_man.list_index &= 0x7;

			/* 结果处理 */
			loop(4)
			{
				adc_man.list[index][adc_man.list_index] = adc_man.sum[index];
				adc_man.sum[index] = 0;
			}

			/* 开始自校正 */
			adc_man.tune_st = 1;
			// adc_calibration_init(ADC1);
		}
		else
		{
			/* 使能扫描模式 */
			ADC1->CTRL1_B.SCANEN = BIT_SET;
			ADC1->CTRL2_B.INJSWSC = BIT_SET;
		}
	}
	else
	{
		/* 超时 */
		adc_man.time_out++;
		if (adc_man.time_out > 3)
		{
			adc_init();
			// 触发注入组
			ADC1->CTRL1_B.SCANEN = BIT_SET;
			ADC1->CTRL2_B.INJSWSC = BIT_SET;
		}
	}
}

/******************************************************************************
 * @brief   Adc task.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void adc_regular_handle(void)
{
	if (adc_man.tune_st == 1)
	{
		/* 校准 */
		// adc_calibration_start(ADC1);
		adc_man.tune_st = 2;
	}
	else if (adc_man.tune_st == 2)
	{
		adc_man.tune_st = 0;

		/* 开启普通规则转换 */
		adc_regular_start();
	}
	// else if (ADC1->sts_bit.occe)
	else if (dma_comp_flag_get(&DMA_ADC))
	{
		adc_man.time_out = 0;
		adc_man.cnt++;
		ADC1->STS = 0;

		/* 累加 */
		loop(ADC_CH_NUM)
		{
			adc_man.sum[index] += adc_man.real[index];
		}

		/* 电压判断 */
		adc_for_sys_vol();

		/* 过采样，工频倍数，取100ms */
		if (adc_man.cnt >= 100)
		{
			adc_man.cnt = 0;
			adc_man.st_hal_end = 1;

			adc_man.list_index++;
			adc_man.list_index &= 0x7;

			/* 结果处理 */
			loop(ADC_CH_NUM)
			{
				adc_man.list[index][adc_man.list_index] = adc_man.sum[index];
				adc_man.sum[index] = 0;
			}

			/* 开始自校正 */
			adc_man.tune_st = 1;
			// adc_calibration_init(ADC1);
		}
		else
		{
			/* 开启普通规则转换 */
			adc_regular_start();
		}
	}
	else
	{
		/* 超时 */
		adc_man.time_out++;
		if (adc_man.time_out > 3)
		{
			adc_init();

			/* 开启普通规则转换 */
			adc_regular_start();
		}
	}
}

/******************************************************************************
 * @brief   Adc vol.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
adc_vol_type sys_vol;

#define ADC_VAL_24V (240UL * 4096 / (21 * 33))
#if DBG_EN > 0
#define ADC_VAL_RDY (ADC_VAL_24V * 10 / 24) // 10V
#define ADC_VAL_LOW (ADC_VAL_24V * 8 / 24)	// 8V
#else
#define ADC_VAL_RDY (ADC_VAL_24V * 20 / 24) // 20V
#define ADC_VAL_LOW (ADC_VAL_24V * 18 / 24) // 18V
#endif
#define ADC_VAL_FLT_SV 8

void adc_for_sys_vol(void)
{
	uu16 vol;

	vol = adc_man.real[0] + adc_man.real[2];
	vol = vol >> 1;
	sys_vol.ad_val = vol;

	// 上电判定
	if ((vol >= ADC_VAL_RDY) && (sys_vol.flt < ADC_VAL_FLT_SV))
	{
		sys_vol.flt++;
		if (sys_vol.flt >= ADC_VAL_FLT_SV)
		{
			sys_vol.st = 1;
		}
	}

	// 掉电判定
	if ((vol <= ADC_VAL_LOW) && (sys_vol.flt != 0))
	{
		sys_vol.flt--;
		if (0 == sys_vol.flt)
		{
			sys_vol.st = 0;
		}
	}
}

/******************************************************************************
 * @brief   Adc init.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void adc_init(void)
{
	intx_alloc();

	intx_disable();

	/* 时钟开启 */
	RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
	RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_ADC1);
	RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_ADC1);

	intx_enable();

	/* 通用配置 */
	ADC->CCTRL = 0;
	ADC->CCTRL_B.ADCPRE = 3; // PCLK2 8分频
	ADC->CCTRL_B.VBATEN = 1;
	ADC->CCTRL_B.TSVREFEN = 1;

	/* 模块配置 */
	ADC1->CTRL2 = 0;

	/* 开始配置 */
	ADC1->CTRL1 = 0;
	ADC1->CTRL1_B.SCANEN = BIT_SET; // 使能扫描模式

	/* 触发方式 */
	ADC1->CTRL2_B.INJEXTTRGEN = 0;
	ADC1->CTRL2_B.REGEXTTRGEN = 0;

	/* 注入方式结果偏移量 */
	ADC1->INJDOF1 = 0;
	ADC1->INJDOF2 = 0;
	ADC1->INJDOF3 = 0;
	ADC1->INJDOF4 = 0;

	/* 采样时间 */
	adc_sampletime_cfg();

	/* 看门狗 */
	ADC1->AWDLT = 0x0FFF;
	ADC1->AWDHT = 0x0000;

	/* 转换通道配置 */
	adc_trans_channel_cfg();

	/* DMA */
	adc_dma_cfg();
	ADC1->CTRL2_B.DMAEN = 1;
	ADC1->CTRL2_B.DMADISSEL = 1;

	/* 使能ADC */
	ADC1->CTRL2_B.ADCEN = 1;

	/* 数据初始化 */
	adc_man.cnt = 16;
	memset(&adc_man, 0, sizeof(adc_man));
	adc_man.list_index = 0;

	/* adc on 2个adc时钟后允许操作 */
	bsp_delay_us(10);

	/* 校准 */
	// adc_calibration_init(ADC1);
	// while (adc_calibration_init_status_get(ADC1))
	;
	// adc_calibration_start(ADC1);
	// while (adc_calibration_status_get(ADC1))
	;

	bsp_delay_us(10);
}

/******************************************************************************
 * @brief   Adc sampletime config.
 * @param   none
 * @return  none
 *****************************************************************************/
void adc_sampletime_cfg(void)
{
	ADC1->SMPTIM1 =
		(0x07UL << 7 * 3) | // SPT17
		(0x07UL << 6 * 3) | // SPT16
		(0x04UL << 5 * 3) | // SPT15
		(0x04UL << 4 * 3) | // SPT14
		(0x04UL << 3 * 3) | // SPT13
		(0x04UL << 2 * 3) | // SPT12
		(0x04UL << 1 * 3) | // SPT11
		(0x04UL << 0 * 3);	// SPT10

	ADC1->SMPTIM2 =
		(0x06UL << 9 * 3) | // SPT9
		(0x06UL << 8 * 3) | // SPT8
		(0x04UL << 7 * 3) | // SPT7
		(0x04UL << 6 * 3) | // SPT6
		(0x04UL << 5 * 3) | // SPT5
		(0x04UL << 4 * 3) | // SPT4
		(0x04UL << 3 * 3) | // SPT3
		(0x04UL << 2 * 3) | // SPT2
		(0x06UL << 1 * 3) | // SPT1
		(0x06UL << 0 * 3);	// SPT0
}

/******************************************************************************
 * @brief   Adc trans channel config.
 * @param   none
 * @return  none
 *****************************************************************************/
void adc_trans_channel_cfg(void)
{
	/* 注入组配置: 	 RL              iSQ 4          iSQ 3         iSQ 2        iSQ 1 */
	ADC1->INJSEQ = (0x03UL << 20) | (16UL << 15) | (4UL << 10) | (1UL << 5) | (0UL << 0);

	/* 规则组配置 */
	/*            	OSN1         OSN2         OSN3          OSN4          OSN5          OSN6 */
	ADC1->REGSEQ3 = (0UL << 0) | (1UL << 5) | (4UL << 10) | (16UL << 15) | (17UL << 20) | (0UL << 25);
	/*            	OSN7         OSN8         OSN9          OSN10         OSN11         OSN12 */
	ADC1->REGSEQ2 = (0UL << 0) | (0UL << 5) | (0UL << 10) | (0UL << 15) | (0UL << 20) | (0UL << 25);
	/*            	OSN13        OSN14        OSN15         OSN116        LEN     */
	ADC1->REGSEQ1 = (0UL << 0) | (0UL << 5) | (0UL << 10) | (0UL << 15) | ((ADC_CH_NUM - 1) << 20);
}

/******************************************************************************
 * @brief   Adc dma config.
 * @param   none
 * @return  none
 *****************************************************************************/
void adc_dma_cfg(void)
{
	const app_dma_type *dmax = &DMA_ADC;
	DMA_Config_T dma_init_struct;

	DMA_ConfigStructInit(&dma_init_struct);

	/* 通道配置 */
	dma_init_struct.channel = dmax->trig_src;

	dma_init_struct.bufferSize = ADC_CH_NUM;
	dma_init_struct.memoryDataSize = DMA_MEMORY_DATA_SIZE_HALFWORD;
	dma_init_struct.memoryInc = DMA_MEMORY_INC_ENABLE;
	dma_init_struct.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD;
	dma_init_struct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
	dma_init_struct.priority = DMA_PRIORITY_HIGH;
	dma_init_struct.loopMode = DMA_MODE_NORMAL;

	dma_init_struct.memoryBaseAddr = (uint32_t)(adc_man.real);
	dma_init_struct.peripheralBaseAddr = (uint32_t)(&ADC1->REGDATA);
	dma_init_struct.dir = DMA_DIR_PERIPHERALTOMEMORY;

	dma_init_struct.fifoMode = DMA_FIFOMODE_DISABLE;
	dma_init_struct.memoryBurst = DMA_MEMORYBURST_SINGLE;
	dma_init_struct.peripheralBurst = DMA_PERIPHERALBURST_SINGLE;

	/* 初始化 */
	dma_stream_deinit(&DMA_ADC);

	DMA_Config(dmax->stream, &dma_init_struct);

	/* 设置长度 */
	dma_stream_set_data_len(&DMA_ADC, ADC_CH_NUM);
}

/******************************************************************************
 * @brief   Adc dma start.
 * @param   none
 * @return  none
 *****************************************************************************/
void adc_regular_start(void)
{
	/* 重置DMA */
	dma_stream_disable(&DMA_ADC);

	dma_stream_set_mem_addr(&DMA_ADC, (uint32_t)(adc_man.real));

	dma_stream_set_data_len(&DMA_ADC, ADC_CH_NUM);

	dma_stream_enable(&DMA_ADC);

	/* 启动转换 */
	ADC1->CTRL1_B.SCANEN = BIT_SET;
	ADC1->CTRL2_B.REGSWSC = BIT_SET;
}
